home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / BOUNCE / BOUNCE.C next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  20.0 KB  |  944 lines

  1.  
  2. /**************************************************************************
  3.  *                                      *
  4.  *      Copyright (C) 1988, 1989, 1990, Silicon Graphics, Inc.          *
  5.  *                                      *
  6.  *  These coded instructions, statements, and computer programs  contain  *
  7.  *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
  8.  *  are protected by Federal copyright law.  They  may  not be disclosed  *
  9.  *  to  third  parties  or copied or duplicated in any form, in whole or  *
  10.  *  in part, without the prior written consent of Silicon Graphics, Inc.  *
  11.  *                                      *
  12.  **************************************************************************/
  13.  
  14. /*
  15.  *  foo $Revision: 1.4 $
  16.  */
  17. #include <assert.h>
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <GL/glut.h>
  24.  
  25. #include "tb.h"
  26. #include "glui.h"
  27.  
  28. /* Some <math.h> files do not define M_PI... */
  29. #ifndef M_PI
  30. #define M_PI 3.14159265358979323846
  31. #endif
  32.  
  33. #define UDIV 12
  34. #define VDIV 12
  35.  
  36. #define WALLGRIDMAX 32
  37. #define EYEZ 3.3
  38.  
  39. #define TOTALBALLS 3
  40.  
  41. #define R 0
  42. #define G 1
  43. #define B 2
  44.  
  45. #define X 0
  46. #define Y 1
  47. #define Z 2
  48. #define W 3
  49.  
  50. int wallgrid = 8; /* sqrt of the number of quads in a wall */
  51. float fatt = 1.0;
  52.  
  53. int freeze = GL_FALSE;
  54. int spin = GL_FALSE;
  55. int spinning = GL_FALSE;
  56. int objecton = GL_FALSE;
  57. int normson = GL_FALSE;
  58. int lighton[3] = {GL_TRUE, GL_TRUE, GL_TRUE};
  59.  
  60. int window;                /* main window id */
  61.  
  62. GLboolean performance = GL_FALSE;    /* performance indicator */
  63.  
  64. struct {
  65.    float p[3];
  66.    float d[3];
  67.    unsigned char color[3];
  68. } balls[TOTALBALLS];
  69.  
  70. float ballobj[UDIV+1][VDIV+1][4];
  71. float wallobj[WALLGRIDMAX+1][WALLGRIDMAX+1][4];
  72. float wallnorms[WALLGRIDMAX+1][WALLGRIDMAX+1][3];
  73. float wallnorm[3] = { 0.0, 0.0, -1.0 };
  74.  
  75. int orx, ory;
  76.  
  77. float ballscale;
  78. float ballsize;
  79.  
  80. int DELTAX, DELTAY;
  81.  
  82. int lflag = 0;
  83.  
  84. float newpos[] = { 0.0, 0.0, 0.0, 1.0 };
  85.  
  86. GLfloat light_Ka[] = { 0.3, 0.3, 0.3, 1.0 };  /* ambient */
  87. GLfloat light_Ks[] = { 0.0, 0.0, 0.0, 1.0 };  /* specular */
  88.  
  89. GLfloat light0_Ka[]  = { 0.0, 0.0, 0.0, 1.0 };  /* ambient */
  90. GLfloat light0_Kd[]  = { 1.0, 0.1, 0.1, 1.0 };  /* diffuse */
  91. GLfloat light0_pos[] = { 0.0, 0.0, 0.0, 1.0 };  /* position */
  92.  
  93. GLfloat light1_Ka[]  = { 0.0, 0.0, 0.0, 1.0 };  /* ambient */
  94. GLfloat light1_Kd[]  = { 0.1, 1.0, 0.1, 1.0 };  /* diffuse */
  95. GLfloat light1_pos[] = { 0.0, 0.0, 0.0, 1.0 };  /* position */
  96.  
  97. GLfloat light2_Ka[]  = { 0.0, 0.0, 0.0, 1.0 };  /* ambient */
  98. GLfloat light2_Kd[]  = { 0.1, 0.1, 1.0, 1.0 };  /* diffuse */
  99. GLfloat light2_pos[] = { 0.0, 0.0, 0.0, 1.0 };  /* position */
  100.  
  101. GLfloat attenuation[] = { 1.0, 3.0 };
  102.  
  103. GLfloat plane_Ka[] = { 0.0, 0.0, 0.0, 1.0 };  /* ambient */
  104. GLfloat plane_Kd[] = { 0.4, 0.4, 0.4, 1.0 };  /* diffuse */
  105. GLfloat plane_Ks[] = { 1.0, 1.0, 1.0, 1.0 };  /* specular */
  106. GLfloat plane_Ke[] = { 0.0, 0.0, 0.0, 1.0 };  /* emission */
  107. GLfloat plane_Se   = 30.0;                    /* shininess */
  108.  
  109. GLfloat wall_Ka[] = { 0.1, 0.1, 0.1, 1.0 };  /* ambient */
  110. GLfloat wall_Kd[] = { 0.8, 0.8, 0.8, 1.0 };  /* diffuse */
  111. GLfloat wall_Ks[] = { 1.0, 1.0, 1.0, 1.0 };  /* specular */
  112. GLfloat wall_Ke[] = { 0.0, 0.0, 0.0, 1.0 };  /* emission */
  113. GLfloat wall_Se   = 20.0;                    /* shininess */
  114.  
  115. GLuint wall_material, plane_material; /* material display lists */
  116.  
  117. char ofile[80];
  118.  
  119.  
  120. /************************************************************/
  121. /* XXX - The following is an excerpt from spin.h from spin  */
  122. /************************************************************/
  123.  
  124. #define POLYGON    1
  125. #define LINES    2
  126. #define TRANSPERENT 3
  127. #define DISPLAY    4
  128. #define LMATERIAL 5
  129.  
  130. #define FASTMAGIC    0x5423
  131.  
  132. typedef struct fastobj {
  133.     int npoints;
  134.     int colors;
  135.     int type;
  136.     int material;
  137.     int display;
  138.     int ablend;
  139.     GLint *data;
  140. } fastobj;
  141.  
  142. /*
  143.  * Wrappers to do either lines or polygons
  144.  */
  145. #define PolyOrLine()    if (lflag == LINES) { \
  146.                 glBegin(GL_LINE_LOOP); \
  147.             } else { \
  148.                 glBegin(GL_POLYGON); \
  149.             }
  150.  
  151. #define EndPolyOrLine() if (lflag == LINES) { \
  152.                 glEnd(); \
  153.             } else { \
  154.                 glEnd(); \
  155.             }
  156.  
  157. /************************* end of spin.h excerpt *************************/
  158.  
  159.  
  160. fastobj    *obj = NULL;
  161.  
  162. /* 
  163.  
  164.    general purpose text routine.  draws a string according to the
  165.    format in a stroke font at x, y after scaling it by the scale
  166.    specified.  x, y and scale are all in window-space [i.e., pixels]
  167.    with origin at the lower-left.
  168.  
  169. */
  170.  
  171. void 
  172. text(GLuint x, GLuint y, GLfloat scale, char* format, ...)
  173. {
  174.     va_list args;
  175.     char buffer[255], *p;
  176.     GLfloat font_scale = 119.05 + 33.33;
  177.  
  178.     va_start(args, format);
  179.     vsprintf(buffer, format, args);
  180.     va_end(args);
  181.  
  182.     glMatrixMode(GL_PROJECTION);
  183.     glPushMatrix();
  184.     glLoadIdentity();
  185.     gluOrtho2D(0, glutGet(GLUT_WINDOW_WIDTH), 0, glutGet(GLUT_WINDOW_HEIGHT));
  186.  
  187.     glMatrixMode(GL_MODELVIEW);
  188.     glPushMatrix();
  189.     glLoadIdentity();
  190.  
  191.     glPushAttrib(GL_ENABLE_BIT);
  192.     glDisable(GL_LIGHTING);
  193.     glDisable(GL_TEXTURE_2D);
  194.     glEnable(GL_DEPTH_TEST);
  195.     glEnable(GL_LINE_SMOOTH);
  196.     glEnable(GL_BLEND);
  197.     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  198.     glTranslatef(x, y, 0.0);
  199.  
  200.     glScalef(scale/font_scale, scale/font_scale, scale/font_scale);
  201.  
  202.     for(p = buffer; *p; p++)
  203.     glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
  204.   
  205.     glPopAttrib();
  206.  
  207.     glPopMatrix();
  208.     glMatrixMode(GL_PROJECTION);
  209.     glPopMatrix();
  210.     glMatrixMode(GL_MODELVIEW);
  211. }
  212.  
  213. float
  214. frand(void)
  215. {
  216.     return 2.0*(rand()/32768.0 - .5);
  217. }
  218.  
  219.  
  220. void
  221. resetballs(void)
  222. {
  223.     register short i;
  224.  
  225.     balls[0].color[R] = 255;
  226.     balls[0].color[G] = 64;
  227.     balls[0].color[B] = 64;
  228.     balls[1].color[R] = 64;
  229.     balls[1].color[G] = 255;
  230.     balls[1].color[B] = 64;
  231.     balls[2].color[R] = 64;
  232.     balls[2].color[G] = 64;
  233.     balls[2].color[B] = 255;
  234.     for (i = 0; i < TOTALBALLS; i++) {
  235.     balls[i].p[0] = 0.0;
  236.     balls[i].p[1] = 0.0;
  237.     balls[i].p[2] = 0.0;
  238.     balls[i].d[0] = .1*frand();
  239.     balls[i].d[1] = .1*frand();
  240.     balls[i].d[2] = .1*frand();
  241.     }
  242. }
  243.  
  244.  
  245. void
  246. drawface(void)
  247. {
  248.     register int i,j;
  249.  
  250.     glNormal3fv(wallnorm);
  251.     for (i=0; i < wallgrid; i++) {
  252.     glBegin(GL_TRIANGLE_STRIP);
  253.     for (j=0; j <= wallgrid; j++) {
  254.         glVertex3fv(wallobj[i][j]);
  255.         glVertex3fv(wallobj[i+1][j]);
  256.     }
  257.     glEnd();
  258.     }
  259. }
  260.  
  261.  
  262. void
  263. drawnorms(void)
  264. {
  265.     register int i,j;
  266.  
  267.     glDisable(GL_LIGHTING);
  268.     glColor3ub(255, 255, 0);
  269.     for (i=0; i <= wallgrid; i++) {
  270.     for (j=0; j <= wallgrid; j++) {
  271.         glBegin(GL_LINES);
  272.         glVertex3fv(wallobj[i][j]);
  273.         glVertex3fv(wallnorms[i][j]);
  274.         glEnd();
  275.     }
  276.     }
  277.     glEnable(GL_LIGHTING);
  278. }
  279.  
  280.  
  281. void
  282. drawbox(void)
  283. {
  284.     glPushMatrix();
  285.  
  286. /*  drawface();        */
  287.     glRotatef(90.0, 0.0, 1.0, 0.0);
  288.     drawface();
  289.     if (normson) drawnorms();
  290.     glRotatef(90.0, 0.0, 1.0, 0.0);
  291.     drawface();
  292.     if (normson) drawnorms();
  293.     glRotatef(90.0, 0.0, 1.0, 0.0);
  294. /*  drawface();        */
  295.     glRotatef(-90.0, 1.0, 0.0, 0.0);
  296.     drawface();
  297.     if (normson) drawnorms();
  298.     glRotatef(180.0, 1.0, 0.0, 0.0);
  299. /*  drawface();        */
  300.     glPopMatrix();
  301. }
  302.  
  303.  
  304. void
  305. drawfastobj(fastobj *obj)
  306. {
  307.     register GLint *p, *end;
  308.     register int npolys;
  309.  
  310.     p = obj->data;
  311.     end = p + 8 * obj->npoints;
  312.  
  313.     if(obj->colors) {
  314.     npolys = obj->npoints/4;
  315.     while(npolys--) {
  316.         PolyOrLine();
  317.         glColor3iv(p);
  318.         glVertex3fv((float *)p+4);
  319.         glColor3iv(p+8);
  320.         glVertex3fv((float *)p+12);
  321.         glColor3iv(p+16);
  322.         glVertex3fv((float *)p+20);
  323.         glColor3iv(p+24);
  324.         glVertex3fv((float *)p+28);
  325.         EndPolyOrLine();
  326.         p += 32;
  327.     }
  328.     } else {
  329.     while ( p < end) {
  330.         PolyOrLine();
  331.         glNormal3fv((float *)p);
  332.         glVertex3fv((float *)p+4);
  333.         glNormal3fv((float *)p+8);
  334.         glVertex3fv((float *)p+12);
  335.         glNormal3fv((float *)p+16);
  336.         glVertex3fv((float *)p+20);
  337.         glNormal3fv((float *)p+24);
  338.         glVertex3fv((float *)p+28);
  339.         EndPolyOrLine();
  340.         p += 32;
  341.     }
  342.     }
  343. }
  344.  
  345. void
  346. drawball(void)
  347. {
  348.     register int i,j;
  349.  
  350.     for (i=0; i < UDIV; i++) {
  351.     for (j=0; j < VDIV; j++) {
  352.         glBegin(GL_POLYGON);
  353.         glVertex4fv( ballobj[i][j] );
  354.         glVertex4fv( ballobj[i+1][j] );
  355.         glVertex4fv( ballobj[i+1][j+1] );
  356.         glVertex4fv( ballobj[i][j+1] );
  357.         glEnd();
  358.     }
  359.     }
  360. }
  361.  
  362.  
  363.  
  364. void
  365. drawimage(void)
  366. {
  367.     register short i;
  368.     static int start, end, last;
  369.  
  370.     glutSetWindow(window);
  371.  
  372.     if (performance)
  373.     start = glutGet(GLUT_ELAPSED_TIME);
  374.  
  375.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  376.  
  377.     glPushMatrix();
  378.     tbMatrix();
  379.  
  380.     for (i=0; i < TOTALBALLS; i++) {
  381.     newpos[0] = balls[i].p[0];
  382.     newpos[1] = balls[i].p[1];
  383.     newpos[2] = balls[i].p[2];
  384.     glLightfv(GL_LIGHT0 + i, GL_POSITION, newpos);
  385.     }
  386.  
  387.     glCallList(wall_material);
  388.     glEnable(GL_LIGHTING);
  389.     drawbox();
  390.  
  391.     glEnable(GL_DEPTH_TEST);
  392.  
  393.     if (objecton)
  394.     {
  395.     glCallList(plane_material);
  396.     glPushMatrix();
  397.     glScalef(1.5, 1.5, 1.5);
  398.     glRotatef(180.0, 0.0, 0.0, 1.0);
  399.     if (spin)
  400.     {
  401.         orx += 50;
  402.         ory += 50;
  403.     }
  404.     glRotatef(orx/10.0, 1.0, 0.0, 0.0);
  405.     glRotatef(ory/10.0, 0.0, 1.0, 0.0);
  406.     drawfastobj(obj);
  407.     glPopMatrix();
  408.     }
  409.  
  410.     glDisable(GL_LIGHTING);
  411.  
  412.     for (i=0; i < TOTALBALLS; i++) {
  413.     if (lighton[i])
  414.     {
  415.         glPushMatrix();
  416.         glTranslatef(balls[i].p[0],balls[i].p[1],balls[i].p[2]);
  417.         glColor3ubv(balls[i].color);
  418.         drawball();
  419.         glPopMatrix();
  420.     }
  421.     }
  422.  
  423.     glColor3f(1.0, 1.0, 1.0);
  424.     if (performance) {
  425.         if (end - last == 0) {
  426.         text(10, 73, 20, "unknown fps");
  427.     } else {
  428.         text(10, 73, 20, "%.0f fps", 1.0 / ((end - last) / 1000.0));
  429.     }
  430.     last = start;
  431.     }
  432.     text(10, 43, 14, "Attenuation [%.2f]", fatt);
  433.     text(10, 13, 14, "Tesselation [%3d]", wallgrid);
  434.  
  435.  
  436.     glPopMatrix();
  437.     glutSwapBuffers();
  438.  
  439.     if (performance)
  440.     end = glutGet(GLUT_ELAPSED_TIME);
  441. }
  442.  
  443.  
  444. void
  445. initobjects(void)
  446. {
  447.     register float u,v,du,dv;
  448.     register short i,j;
  449.  
  450.     du = 2.0*M_PI/UDIV;
  451.     dv = M_PI/VDIV;
  452.  
  453.     u = 0.;
  454.     for (i=0; i <= UDIV; i++) {
  455.     v = 0.;
  456.     for (j=0; j <= VDIV; j++) {
  457.         ballobj[i][j][X] = ballsize*cos(u)*sin(v);
  458.         ballobj[i][j][Y] = ballsize*sin(u)*sin(v);
  459.         ballobj[i][j][Z] = ballsize*cos(v);
  460.         ballobj[i][j][W] = 1.0;
  461.         v += dv;
  462.     }
  463.     u += du;
  464.     }
  465.  
  466.     for (i=0; i <= wallgrid; i++) {
  467.     for (j=0; j <= wallgrid; j++) {
  468.         wallobj[i][j][X] = -1.0 + 2.0*i/wallgrid;
  469.         wallobj[i][j][Y] = -1.0 + 2.0*j/wallgrid;
  470.         wallobj[i][j][Z] = 1.0;
  471.         wallobj[i][j][W] = 1.0;
  472.     }
  473.     }
  474.  
  475.     for (i=0; i <= wallgrid; i++) {
  476.     for (j=0; j <= wallgrid; j++) {
  477.         wallnorms[i][j][X] = wallobj[i][j][X] + wallnorm[X]*0.1;
  478.         wallnorms[i][j][Y] = wallobj[i][j][Y] + wallnorm[Y]*0.1;
  479.         wallnorms[i][j][Z] = wallobj[i][j][Z] + wallnorm[Z]*0.1;
  480.     }
  481.     }
  482. }
  483.  
  484. int MOUSEX, MOUSEY;
  485.  
  486. static void
  487. mouse(int button, int state, int x, int y)
  488. {
  489.     MOUSEX = x;
  490.     MOUSEY = y;
  491.     tbMouse(button, state, x, y);
  492. }
  493.  
  494. static void
  495. motion(int x, int y)
  496. {
  497.     DELTAX -= MOUSEX - x;
  498.     DELTAY += MOUSEY - y;
  499.     MOUSEX = x;
  500.     MOUSEY = y;
  501.     tbMotion(x, y);
  502. }
  503.  
  504. /* ARGSUSED1 */
  505. void
  506. keyboard(unsigned char key, int x, int y)
  507. {
  508.     switch(key) {
  509.     case 27: /* ESC */
  510.     exit(0);
  511.     break;
  512.  
  513.     case '+':
  514.     wallgrid++;
  515.     if (wallgrid > WALLGRIDMAX)
  516.         wallgrid = WALLGRIDMAX;
  517.     initobjects();
  518.     break;
  519.  
  520.     case '-':
  521.     wallgrid--;
  522.     if (wallgrid < 1)
  523.         wallgrid = 1;
  524.     initobjects();
  525.     break;
  526.     }
  527. }
  528.  
  529. void
  530. initialize(void)
  531. {
  532.     glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
  533.     window = glutCreateWindow("bounce");
  534.  
  535.     initobjects();
  536.  
  537.     srand(glutGet(GLUT_ELAPSED_TIME));
  538.  
  539.     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
  540.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_Ka);
  541.  
  542.     plane_material = glGenLists(1);
  543.     glNewList(plane_material, GL_COMPILE);
  544.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, plane_Ka);
  545.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, plane_Kd);
  546.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, plane_Ks);
  547.     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, plane_Ke);
  548.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, plane_Se);
  549.     glEndList();
  550.  
  551.     wall_material = glGenLists(1);
  552.     glNewList(wall_material, GL_COMPILE);
  553.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, wall_Ka);
  554.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, wall_Kd);
  555.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, wall_Ks);
  556.     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, wall_Ke);
  557.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, wall_Se);
  558.     glEndList();
  559.  
  560.     glLightfv(GL_LIGHT0, GL_AMBIENT, light0_Ka);
  561.     glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_Kd);
  562.     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, attenuation[0]);
  563.     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, attenuation[1]);
  564.     /* OpenGL's light0 has different specular properties than the rest
  565.        of the lights.... */
  566.     glLightfv(GL_LIGHT0, GL_SPECULAR, light_Ks);
  567.  
  568.     glLightfv(GL_LIGHT1, GL_AMBIENT, light1_Ka);
  569.     glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_Kd);
  570.     glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, attenuation[0]);
  571.     glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, attenuation[1]);
  572.  
  573.     glLightfv(GL_LIGHT2, GL_AMBIENT, light2_Ka);
  574.     glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_Kd);
  575.     glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, attenuation[0]);
  576.     glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, attenuation[1]);
  577.  
  578.     glutMotionFunc(motion);
  579.     glutMouseFunc(mouse);
  580.     glutKeyboardFunc(keyboard);
  581. }
  582.  
  583.  
  584. void
  585. calcball(void)
  586. {
  587.     register short i,j;
  588.  
  589.     for (j=0; j < TOTALBALLS; j++) {
  590.     for (i=0; i < 3; i++) {
  591.         balls[j].p[i] += balls[j].d[i];
  592.         if (fabs(balls[j].p[i]) > ballscale) {
  593.         balls[j].p[i] = (balls[j].p[i] > 0.0) ?
  594.         ballscale : -ballscale;
  595.         balls[j].d[i] = -balls[j].d[i];
  596.         }
  597.     }
  598.     }
  599. }
  600.  
  601. static void menu(int value);
  602. static void idle(void);
  603.  
  604. static void
  605. make_menu(void)
  606. {
  607.     static int main_menu = 0;
  608.  
  609.     if (main_menu)
  610.     glutDestroyMenu(main_menu);
  611.  
  612.     main_menu = glutCreateMenu(menu);
  613.     glutAddMenuEntry("bounce", 0);
  614.     glutAddMenuEntry("", 0);
  615.     if (lighton[0])
  616.     glutAddMenuEntry("red light off", 1);
  617.     else
  618.     glutAddMenuEntry("red light on", 1);
  619.     if (lighton[1])
  620.     glutAddMenuEntry("green light off", 2);
  621.     else
  622.     glutAddMenuEntry("green light on", 2);
  623.     if (lighton[2])
  624.     glutAddMenuEntry("blue light off", 3);
  625.     else
  626.     glutAddMenuEntry("blue light on", 3);
  627.  
  628.     if (freeze)
  629.     glutAddMenuEntry("unfreeze lights", 4);
  630.     else
  631.     glutAddMenuEntry("freeze lights", 4);
  632.  
  633.     if (normson)
  634.     glutAddMenuEntry("normals off", 7);
  635.     else
  636.     glutAddMenuEntry("normals on", 7);
  637.  
  638.     if (performance)
  639.     glutAddMenuEntry("frame rate off", 8);
  640.     else
  641.     glutAddMenuEntry("frame rate on", 8);
  642.  
  643.     if (obj)
  644.     {
  645.     if (objecton)
  646.         glutAddMenuEntry("object off", 5);
  647.     else
  648.         glutAddMenuEntry("object on", 5);
  649.     if (spin)
  650.         glutAddMenuEntry("object spin off", 6);
  651.     else
  652.         glutAddMenuEntry("object spin on", 6);
  653.     }
  654.  
  655.     glutAddMenuEntry("", 0);
  656.     glutAddMenuEntry("exit", 9);
  657.  
  658.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  659. }
  660.  
  661. static void
  662. menu(int value)
  663. {
  664.     switch(value) {
  665.     case 1:
  666.     if ((lighton[0] = !lighton[0]))
  667.         glEnable(GL_LIGHT0);
  668.     else
  669.         glDisable(GL_LIGHT0);
  670.     break;
  671.     case 2:
  672.     if ((lighton[1] = !lighton[1]))
  673.         glEnable(GL_LIGHT1);
  674.     else
  675.         glDisable(GL_LIGHT1);
  676.     break;
  677.     case 3:
  678.     if ((lighton[2] = !lighton[2]))
  679.         glEnable(GL_LIGHT2);
  680.     else
  681.         glDisable(GL_LIGHT2);
  682.     break;
  683.     case 4:
  684.     freeze =  !freeze;
  685.         if (!freeze || spinning) {
  686.       glutIdleFunc(idle);
  687.         } else {
  688.       glutIdleFunc(NULL);
  689.         }
  690.     break;
  691.     case 5:
  692.     if (obj)
  693.         objecton =  !objecton;
  694.     else
  695.         exit(1);
  696.     break;
  697.     case 6:
  698.     spin =  !spin;
  699.     break;
  700.     case 7:
  701.         normson = !normson;
  702.         break;
  703.     case 8:
  704.     performance = !performance;
  705.     break;
  706.     case 9:
  707.     exit(0);
  708.     break;
  709.     }
  710.     glutPostWindowRedisplay(window);
  711.     make_menu();
  712. }
  713.  
  714. /**********************************************************/
  715. /* XXX - The following is a clone of fastobj.c from spin  */
  716. /**********************************************************/
  717.  
  718.  
  719. fastobj*
  720. readfastobj(char *name)
  721. {
  722.     FILE *inf;
  723.     fastobj *obj;
  724.     int i;
  725.     int nlongs;
  726.     int magic;
  727.     GLint *ip;
  728.     char filename[512];
  729.  
  730.     inf = fopen(name,"r");
  731.     if(!inf) {
  732.       sprintf(filename,"%s",name);
  733.     inf = fopen(filename,"r");
  734.     if(!inf) {
  735.         fprintf(stderr,"readfast: can't open input file %s\n",name);
  736.         exit(1);
  737.     }
  738.     }
  739.     fread(&magic,sizeof(int),1,inf);
  740.     if(magic != FASTMAGIC) {
  741.     fprintf(stderr,"readfast: bad magic in object file\n");
  742.     fclose(inf);
  743.     exit(1);
  744.     }
  745.     obj = (fastobj *)malloc(sizeof(fastobj));
  746.     fread(&obj->npoints,sizeof(int),1,inf);
  747.     fread(&obj->colors,sizeof(int),1,inf);
  748.  
  749.     /*
  750.      * Insure that the data is quad-word aligned and begins on a page
  751.      * boundary.  This shields us from the performance loss which occurs 
  752.      * whenever we try to fetch data which straddles a page boundary  (the OS
  753.      * has to map in the next virtual page and re-start the DMA transfer).
  754.      */
  755.     nlongs = 8 * obj->npoints;
  756.     obj->data = (GLint *) malloc(nlongs*sizeof(int) + 4096);
  757.     obj->data = (GLint *) (((int)(obj->data)) + 0xfff);
  758.     obj->data = (GLint *) (((int)(obj->data)) & 0xfffff000);
  759.  
  760.     /* XXX Careful, sizeof(GLint) could change from implementation
  761.        to implementation making this file format implementation
  762.        dependent. -mjk */
  763.     for (i = 0, ip = obj->data;  i < nlongs/4;  i++, ip += 4)
  764.     fread(ip, 3 * sizeof(GLint), 1, inf);
  765.     fclose(inf);
  766.     return obj;
  767. }
  768.  
  769.  
  770. /*
  771.  * objmaxpoint
  772.  *
  773.  * find the vertex farthest from the origin,
  774.  * so we can set the near and far clipping planes tightly.
  775.  */
  776.  
  777. #define MAXVERT(v) if ( (len = sqrt(    (*(v))  *  (*(v))  +           \
  778.                     (*(v+1)) * (*(v+1)) +           \
  779.                     (*(v+2)) * (*(v+2)) )) > max)  \
  780.             max = len;
  781.  
  782. float
  783. objmaxpoint(obj)
  784. fastobj *obj;
  785. {
  786.     register float *p, *end;
  787.     register int npolys;
  788.     register float len;
  789.     register float max = 0.0;
  790.  
  791.     p = (float *) (obj->data);
  792.  
  793.     if (obj->colors) {
  794.     npolys = obj->npoints/4;
  795.     while(npolys--) {
  796.         MAXVERT(p+4);
  797.         MAXVERT(p+12);
  798.         MAXVERT(p+20);
  799.         MAXVERT(p+28);
  800.         p += 32;
  801.     }
  802.     } else {
  803.     end = p + 8 * obj->npoints;
  804.     while ( p < end) {
  805.         MAXVERT(p+4);
  806.         MAXVERT(p+12);
  807.         MAXVERT(p+20);
  808.         MAXVERT(p+28);
  809.         p += 32;
  810.     }
  811.     }
  812.  
  813.     return max;
  814. }
  815.  
  816. static void
  817. idle(void)
  818. {
  819.     assert(!freeze || spinning);
  820.     if (!freeze) {
  821.         calcball();
  822.     }
  823.     if (spinning) {
  824.         tbStepAnimation();
  825.     }
  826.     glutPostWindowRedisplay(window);
  827. }
  828.  
  829. /* When not visible, stop animating.  Restart when visible again. */
  830. static void 
  831. visible(int vis)
  832. {
  833.   if (vis == GLUT_VISIBLE) {
  834.     if (!freeze || spinning)
  835.       glutIdleFunc(idle);
  836.   } else {
  837.     if (!freeze || spinning)
  838.       glutIdleFunc(NULL);
  839.   }
  840. }
  841.  
  842. static void
  843. reshape(int width, int height)
  844. {
  845.     glViewport(0, 0, width, height);
  846.     glMatrixMode(GL_PROJECTION);
  847.     glLoadIdentity();
  848.     gluPerspective(60.0, (float)width/height, EYEZ-2.0, EYEZ+2.0);
  849.     glMatrixMode(GL_MODELVIEW);
  850.     glLoadIdentity();
  851.     glTranslatef(0.0, 0.25, -EYEZ);
  852.  
  853.     tbReshape(width, height);
  854.     gluiReshape(width, height);
  855. }
  856.  
  857. void
  858. update_fatt(float value)
  859. {
  860.     fatt = 5 * value;
  861.     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, fatt);
  862.     glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, fatt);
  863.     glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, fatt);
  864.     glutPostWindowRedisplay(window);
  865. }
  866.  
  867. void
  868. update_grid(float value)
  869. {
  870.     wallgrid = WALLGRIDMAX*value;
  871.     if (wallgrid < 1)
  872.     wallgrid = 1;
  873.     initobjects();
  874.     glutPostWindowRedisplay(window);
  875. }
  876.  
  877. void
  878. spinChange(int state)
  879. {
  880.   spinning = state;
  881.   if (spinning || !freeze) {
  882.     glutIdleFunc(idle);
  883.   } else {
  884.     glutIdleFunc(NULL);
  885.   }
  886. }
  887.  
  888. int
  889. main(int argc, char **argv)
  890. {
  891.     glutInitWindowSize(512, 512);
  892.     glutInitWindowPosition(64, 64);
  893.     glutInit(&argc, argv);
  894.  
  895.     if (argc > 1)
  896.     {
  897.     int i;
  898.  
  899.     for (i=0; argv[1][i] != '/' && argv[1][i] != '\0'; i++);
  900.     if (argv[1][i] != '/')
  901.     {
  902.         strcpy(ofile, "/usr/demos/data/models/");
  903.         strcat(ofile, argv[1]);
  904.     }
  905.     else
  906.         strcpy(ofile, argv[1]);
  907.  
  908.     if (obj = readfastobj(ofile))
  909.         objecton = GL_TRUE;
  910.     }
  911.  
  912.     ballsize = .04;
  913.     ballscale = 1.0 - ballsize;
  914.  
  915.     initialize();
  916.  
  917.     make_menu();
  918.  
  919.     resetballs();
  920.  
  921.     /* Use local lights for the box */
  922.     glEnable(GL_LIGHT0);
  923.     glEnable(GL_LIGHT1);
  924.     glEnable(GL_LIGHT2);
  925.  
  926.     make_menu();
  927.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  928.  
  929.     glutDisplayFunc(drawimage);
  930.     glutReshapeFunc(reshape);
  931.     glutVisibilityFunc(visible);
  932.  
  933.     gluiHorizontalSlider(window, 130, -10, -10, 20,
  934.              (float)wallgrid/WALLGRIDMAX, update_grid);
  935.     gluiHorizontalSlider(window, 130, -40, -10, 20, fatt/5.0, update_fatt);
  936.  
  937.     tbInit(GLUT_LEFT_BUTTON);
  938.     tbAnimate(1);
  939.     tbAnimateFunc(spinChange);
  940.  
  941.     glutMainLoop();
  942.     return 0;             /* ANSI C requires main to return int. */
  943. }
  944.